指针和常量

  使用一个指针时涉及到两个对象:该指针本身和被它所指的对象。将一个指针的声明用const“预先固定”将使那个对象而不是使这个指针成为常量。要将指针本身而不是被指对象声明为常量,我们必须使用声明运算符* const,而不能只用简单的const。例如,

    void f1(char* p)
    {
        char s[] = "Gorm";

        const char* pc = s;        // 指向常量
        pc[3] = 'g';               // 错误❌:pc是指向常量的
        pc = p;                    // ok

        char* const cp = s;        // 常量指针
        cp[3] = 'g';               // ok
        cp = p;                    // 错误❌:cp是常量指针

        const char* const cpcp = s;    // 到const的const指针
        cpc[3] = 'a';                  // 错误❌:cpc指向常量
        cpc = p;                       // 错误❌:cpc本身是常量
    }

定义常量指针的声明运算符是* const。并没有const * 声明符,所以出现在 * 之前的const是作为基础类型的一部分。例如,

    char* const cp;     // 到char的const指针
    char const* pc;     // 到const char的指针
    const char* pc2;    // 到const char的指针

有人发现从右向左读这种定义很有帮助。例如,“cp是一个const指针到char”,以及“pc2是一个指针指到const char”。

  一个某时通过指针访问当做常量的对象,也完全可能在以其他方式访问时被作为变量。对于函数参数而言,这个情况就特别有用。通过将指针参数声明为const,就禁止了这个函数对被指参数的修改。例如,

char* strcpy(char* p, const char* q);        // 不能修改*q

你可以将一个变量的地址赋给一个到常量的指针,因为这样做不会造成任何伤害。当然,不能将常量的地址赋给一个未加限制的指针,因为这样将会允许修改该对象的值了。例如,

    int a = 1;
    const int c = 2;
    const int* p1 = &c;        // ok
    const int* p2 = &a;        // ok
    int* p3 = &c;              // 错误❌:用const int*对int*进行初始化
    *p3 = 7;                   // 试图修改c的值

可以通过对const指针的显式类型转换,明确要求去掉这种限制(10.2.7.1节和15.4.2.1节)。

🔚